<script setup lang="ts">
import * as QuestionApi from "@/api/train/question";
import TabBar from "./components/tab-bar.vue";
import Common from "./common.vue";
import { onBeforeRouteLeave, useRoute, useRouter } from "vue-router";
import { getCorrectCount, getWrongCount } from "./common";
import {
  PracticeType,
  Question,
  QuestionChapter,
  QuestionActionRecord,
  QuestionState,
  UpdateActionRecordParams,
  QuestionOptionIndex,
  PracticeMode,
  QuestionActionRecordSource,
  QuestionActionRecordWithId,
} from "@/types/practice";
import * as CourseApi from "@/api/train/course";
import { showDialog } from "@nutui/nutui";
import { useCourseStore } from "@/store/modules/course";

const props = defineProps<{
  // 模式
  type: PracticeType;
}>();

const route = useRoute();
const router = useRouter();
const courseStore = useCourseStore();

// id，模式为set的时候则为题集id
const loadId = route.query.id as string;

// 上传记录时的sourceFromId
const itemId = route.query.itemId as string;
// 课程id
const courseId = route.query.courseId as string;

// 加载题目
const { type: loadType } = props;

// 用于持久化做题进度
const uniqueFlag = {
  set: `${loadType}-${loadId}`,
  wrong: "",
  favorite: "",
}[loadType];

const carType = +(route.query.carType ?? "1") as Question["carType"];
const subject = +(route.query.subject ?? "1") as Question["subject"];

// 按需加载id列表
const loadQuestionIds = {
  set: () => QuestionApi.listQuestionIdBySetId(loadId).then((res) => res.data),
  wrong: async () => {
    const courseId = route.query.courseId as string;
    const chapterId = (route.query.chapterId ?? undefined) as QuestionChapter["id"];
    const res = await QuestionApi.listWrongQuestionIds(courseId, chapterId);
    return res.data;
  },
  favorite: async () => {
    const courseId = route.query.courseId as string;
    const chapterId = (route.query.chapterId ?? undefined) as QuestionChapter["id"];
    const res = await QuestionApi.listCollectQuestionIds(courseId, chapterId);
    return res.data;
  },
}[loadType];

// 需要加载和上传做题记录
const needLoadRecord = loadType !== "wrong";

/** 加载题目id列表 */
const questionIds = ref<Question["id"][]>([]);

/** 收藏记录 */
const collectRecordMap = reactive(new Map<Question["id"], boolean>());
/** 更新收藏记录 */
const handleUpdateCollectRecord = (questionId: Question["id"], isCollect: boolean) => collectRecordMap.set(questionId, isCollect);
/** 上传收藏记录 */
const handleUploadCollectRecord = () => {
  const status: QuestionApi.CollectRecordInfo[] = [];
  collectRecordMap.forEach((value, key) => status.push({ questionId: key, ifCollect: value }));
  QuestionApi.createOrUpdateMemberCourseCollect(courseId, status);
};

/** 存储模考本地错题记录 */
const actionRecordMap = reactive(new Map<Question["id"], QuestionActionRecordWithId>());
/** 做题记录模板 */
const actionRecordTemplate: QuestionActionRecord = {
  carType,
  subject,
  lastErrorAnswerRecord: null,
  actionCount: 0,
  errorCount: 0,
  updatedAt: 0,
};
/** 更新做题记录 */
const handleUpdateActionRecord = (params: UpdateActionRecordParams) => {
  const actionRecord = actionRecordMap.get(params.questionId);
  if (actionRecord) {
    actionRecord.actionCount++;
    actionRecord.lastErrorAnswerRecord = params.isCorrect;
    !params.isCorrect && actionRecord.errorCount++;
    actionRecord.updatedAt = Date.now();
  } else {
    actionRecordMap.set(params.questionId, {
      questionId: params.questionId,
      carType: actionRecordTemplate.carType,
      subject: actionRecordTemplate.subject,
      lastErrorAnswerRecord: params.isCorrect,
      actionCount: 1,
      errorCount: params.isCorrect ? 0 : 1,
      updatedAt: Date.now(),
    });
  }
};
/** 上传做题记录 */
const handleUploadActionRecord = () => {
  if (needLoadRecord) {
    const actionRecords: QuestionActionRecordWithId[] = Array.from(actionRecordMap.values()).filter((item) => item.updatedAt);
    actionRecords.length && QuestionApi.batchCreateOrUpdateMemberActionRecord(QuestionActionRecordSource.ITEM, itemId, actionRecords);
  }
};

// 已加载的id和题目的映射
const questionsMap = ref<Map<Question["id"], Question>>(new Map());

/** 整合的题目记录 */
const questionsStateMap = computed(() =>
  questionIds.value.reduce((prev, cur) => {
    const state: QuestionState = {
      loadState: "silent",
      actionRecord: actionRecordMap.get(cur) || actionRecordTemplate,
      question: questionsMap.value.get(cur) || null,
      isCollect: collectRecordMap.get(cur) || false,
    };
    prev.set(cur, state);
    return prev;
  }, new Map<Question["id"], QuestionState>())
);
/** 初始化题目id列表 */
loadQuestionIds().then(async (ids) => {
  // 填充id列表
  questionIds.value = ids!;

  const idsSet = new Set(ids);

  // 加载做题记录
  if (needLoadRecord) {
    const actionRecordRes = await QuestionApi.listMemberActionRecord(QuestionActionRecordSource.ITEM, itemId);
    actionRecordRes.data.filter((record) => idsSet.has(record.questionId)).forEach((record) => actionRecordMap.set(record.questionId, record));
  }

  // 加载收藏记录
  const collectRecordRes = await QuestionApi.listMemberCollectRecord(courseId);
  collectRecordRes.data.forEach((questionId) => collectRecordMap.set(questionId, true));
});

/** 离开页面时上传记录 */
onBeforeRouteLeave(() => {
  handleUploadActionRecord();
  handleUploadCollectRecord();
});

// 答案记录
const questionChoosedAnswerMap = ref(new Map<Question["id"], QuestionOptionIndex[]>());

// 做题记录统计数据
const correctCount = computed(() => getCorrectCount(actionRecordMap));
const wrongCount = computed(() => getWrongCount(actionRecordMap));

/**
 * 选择答案
 * @param questionId 题目id
 * @param optionIndexList 选项
 * @param isCorrect 是否正确
 */
const handleChooseAnswer = (questionId: Question["id"], optionIndexList: QuestionOptionIndex[], isCorrect: boolean) => {
  questionChoosedAnswerMap.value.set(questionId, optionIndexList);
};

// 做题模式
const practiceMode = ref<PracticeMode>("exam");

// 交卷弹窗是否可见
const submitPopupVisible = ref(false);

/**
 * 做完最后一题
 */
const handleEnd = () => {
  // TODO: 弹窗询问：未完成全部题目，是否提交或跳转到未做题目，提交后不可更改，提交的话就把答案全部填满
  // submitPopupVisible.value = true;

  // 当滑动道最后一提时，判断用户是否进入下一个模块
  showDialog({
    title: "跳转提示",
    content: "是否进入下一个模块",
    onCancel: () => {},
    onOk: () => {
      courseStore.updateSkip(true);
      router.back();
    },
  });
};

/** 上传做题进度 */
const uploadStudyRecord = () => {
  const { courseId, itemId } = route.query as { courseId: string | undefined; itemId: string | undefined };
  if (!courseId || !itemId) return;

  const studyProgress = (questionChoosedAnswerMap.value.size / questionIds.value.length) * 100;
  CourseApi.updateStudyRecord({
    courseId,
    itemId,
    studyProgress,
  });
};

// 退出页面前保存记录
onBeforeRouteLeave(uploadStudyRecord);
</script>

<template>
  <div class="min-h-screen bg-gray-1 flex flex-col">
    <!-- 顶部栏 -->
    <TabBar class="h-12 shrink-0 bg-white shadow" v-model:mode="practiceMode" />

    <Common
      :practice-mode="practiceMode"
      v-model:questions-map="questionsMap"
      :question-ids="questionIds"
      :questions-state-map="questionsStateMap"
      :question-choosed-answer-map="questionChoosedAnswerMap"
      :correct-count="correctCount"
      :wrong-count="wrongCount"
      :unique-flag="uniqueFlag"
      @choose-answer="handleChooseAnswer"
      @update-collect-record="handleUpdateCollectRecord"
      @update-action-record="handleUpdateActionRecord"
      @end="handleEnd"
    />

    <!-- 完成答题后的弹窗 -->
    <nut-popup v-model:visible="submitPopupVisible" round>
      <div class="px-3 py-5 bg-white">
        <!-- 是否及格 -->
        <!-- 未答题数、错题数、考试得分 -->
      </div>
    </nut-popup>
  </div>
</template>
